home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- print.c
-
- This module handles printing.
-
- Copyright © 1994-1995, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <string.h>
-
- #include "glob.h"
- #include "print.h"
- #include "dialog.h"
- #include "memutil.h"
- #include "newswatcher.h"
- #include "dummy.h"
- #include "article.h"
- #include "strutil.h"
- #include "drawutil.h"
- #include "ic.h"
- #include "resutil.h"
-
-
-
- #define kPageSetupInfoResourceType 'NWPS'
- #define kPageSetupInfoResourceID 128
-
-
-
- /* Globals used for all kinds of printing. */
-
- static Boolean gPrintText; /* true if printing text, false if printing help topic pict */
- static THPrint gMyHPrint = nil; /* printing handle */
- static Rect gDrawRect; /* drawing rectangle */
- static short gHalfInch; /* num pixels in 0.5 inches */
- static short gMyRefNum; /* ref num of NewsWatcher's resource file */
- static short gFontNum; /* font number */
- static short gFontSize; /* font size */
- static TEHandle gPrintTE; /* textedit handle */
-
- static PrIdleUPP gIdleProcUPP = nil;
-
- /* Globals used for printing picts */
-
- static short gPictResID; /* pict resource id */
-
- /* Globals used for printing text */
-
- static Handle gText; /* text to print */
- static short gLinesPerPage; /* # of lines per page */
- static long gNumLines; /* total # lines */
-
- /* Globals for printing segmented article windows. */
-
- static Boolean gSegmented; /* true if segmented */
- static short gNumSections; /* number of sections */
- static short gCurSection; /* current section in gPrintTE, or -1 if none */
- static long **gSectionBreaks; /* handle to array of section breaks */
- static long **gFirstLines; /* handle to array of section first line numbers */
-
-
-
- /*----------------------------------------------------------------------------
- ReadSavedPageSetupInfoFromPrefs
-
- Read the save page setup info from the NewsWatcher Prefs file.
- ----------------------------------------------------------------------------*/
-
- void ReadSavedPageSetupInfoFromPrefs (void)
- {
- OSErr err = noErr;
-
- err = MyGet1Resource(kPageSetupInfoResourceType, kPageSetupInfoResourceID,
- &gMyHPrint);
- if (err == noErr) MyDetachResource(gMyHPrint);
- }
-
-
-
- /*----------------------------------------------------------------------------
- WritePageSetupInfoToPrefs
-
- Write the page setup info to the NewsWatcher Prefs file.
- ----------------------------------------------------------------------------*/
-
- void WritePageSetupInfoToPrefs (void)
- {
- if (gMyHPrint != nil) {
- MyReplaceResource(gMyHPrint, kPageSetupInfoResourceType,
- kPageSetupInfoResourceID, "\p");
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- PrepSegements
-
- Prepare for printing segmented article windows. Calculate the gFirstLines
- array and the total number of lines.
- ----------------------------------------------------------------------------*/
-
- static void PrepSegmented (void)
- {
- long linesInSection,offset,length;
- short i;
- char state;
-
- state = MyHGetState(gText);
- MyHLock(gText);
- for (i = gNumSections-1; i >= 0; i--) {
- offset = (*gSectionBreaks)[i];
- length = (*gSectionBreaks)[i+1] - offset;
- TESetText(*gText+offset,length, gPrintTE);
- (*gFirstLines)[i] = (**gPrintTE).nLines;
- }
- MyHSetState(gText, state);
-
- gNumLines = 0;
- for (i = 0; i < gNumSections; i++) {
- linesInSection = (*gFirstLines)[i];
- (*gFirstLines)[i] = gNumLines;
- gNumLines += linesInSection;
- }
- (*gFirstLines)[gNumSections] = gNumLines;
- gCurSection = 0;
- }
-
-
-
- /*----------------------------------------------------------------------------
- Prep
-
- Prepare for printing. Calculate the number of lines per page and the
- total number of pages.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr Prep (void)
- {
- short numPages;
-
- if (gPrintText) {
- gLinesPerPage = (gDrawRect.bottom - gDrawRect.top) / (**gPrintTE).lineHeight;
- gLinesPerPage -= 8;
- if (gSegmented) {
- PrepSegmented();
- } else {
- gNumLines = (**gPrintTE).nLines;
- }
- numPages = (gNumLines + gLinesPerPage - 1) / gLinesPerPage;
- } else {
- numPages = 1;
- }
-
- if ((**gMyHPrint).prJob.iLstPage > numPages)
- (**gMyHPrint).prJob.iLstPage = numPages;
- if ((**gMyHPrint).prJob.iLstPage < (**gMyHPrint).prJob.iFstPage) {
- ErrorMessageNumber(kStrPrintNoPagesInRange);
- return userCanceledErr;
- }
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- PrintOnePage
-
- Print one page.
-
- Entry: pageNum = page number.
- title = title for page header.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr PrintOnePage (short pageNum, char *title)
- {
- short vCoord;
- long line, lastLine, length;
- long offset = 0;
- long firstLineThisSection = 0;
- long firstLineNextSection;
- short start,next;
- short i;
- char *sectionStart;
- char state;
- short lineHeight;
- Str255 str;
- CStr255 fmt;
- short pageNumWidth, quarterInch, refNum;
- Rect r;
- PicHandle pict;
- Rect dstRect;
-
- TextFont(gFontNum);
- TextSize(gFontSize);
- TextFace(0);
- TextMode(srcCopy);
-
- lineHeight = (**gPrintTE).lineHeight;
- quarterInch = gHalfInch >> 1;
-
- /* Draw the header. */
-
- vCoord = gDrawRect.top + lineHeight + (**gPrintTE).fontAscent;
- sprintf((char*)str, "%d", pageNum);
- c2pstr((char*)str);
- pageNumWidth = StringWidth(str);
- MoveTo(gDrawRect.right - pageNumWidth - quarterInch, vCoord);
- DrawString(str);
- strcpy((char*)str, title);
- c2pstr((char*)str);
- TruncString(gDrawRect.right - gDrawRect.left - pageNumWidth - 2*gHalfInch,
- str, smTruncEnd);
- MoveTo(gDrawRect.left + quarterInch, vCoord);
- DrawString(str);
- SetRect(&r, gDrawRect.left, gDrawRect.top + lineHeight - 4,
- gDrawRect.right - 2, gDrawRect.top + 2*lineHeight + 5);
- PenPat(&qd.gray);
- PenSize(2, 2);
- FrameRect(&r);
- PenPat(&qd.black);
- PenSize(1, 1);
-
- /* Draw the body of the page (text or pict) */
-
- if (gPrintText) {
-
- state = MyHGetState(gText);
- MyHLock(gText);
-
- line = (pageNum - 1) * gLinesPerPage;
-
- if (line + gLinesPerPage > gNumLines)
- lastLine = gNumLines;
- else
- lastLine = line + gLinesPerPage;
-
- if (gSegmented) {
- for (i = 0; i < gNumSections && line >= (*gFirstLines)[i]; i++) /* do nothing */ ;
- i--;
- offset = (*gSectionBreaks)[i];
- sectionStart = *gText + offset;
- firstLineThisSection = (*gFirstLines)[i];
- firstLineNextSection = (*gFirstLines)[i+1];
- if (i != gCurSection) {
- length = (*gSectionBreaks)[i+1] - offset;
- TESetText(sectionStart,length,gPrintTE);
- gCurSection = i;
- }
- } else {
- sectionStart = *gText;
- }
-
- start = (**gPrintTE).lineStarts[line-firstLineThisSection];
-
- vCoord = gDrawRect.top + 4*lineHeight + (**gPrintTE).fontAscent;
-
- while (true) {
- if (line-firstLineThisSection < (**gPrintTE).nLines-1)
- next = (**gPrintTE).lineStarts[line+1-firstLineThisSection];
- else
- next = (**gPrintTE).teLength;
-
- MoveTo(gDrawRect.left, vCoord);
- DrawText(sectionStart, start, next-start);
- line++;
- if (line == lastLine) break;
-
- start = next;
- if (gSegmented && line >= firstLineNextSection) {
- gCurSection++;
- offset = (*gSectionBreaks)[gCurSection];
- sectionStart = *gText + offset;
- length = (*gSectionBreaks)[gCurSection+1] - offset;
- TESetText(sectionStart, length, gPrintTE);
- firstLineThisSection = firstLineNextSection;
- firstLineNextSection = (*gFirstLines)[gCurSection+1];
- start = 0;
- }
-
- vCoord += lineHeight;
- }
-
- MyHSetState(gText, state);
-
- } else {
-
- pict = GetPicture(gPictResID);
- HNoPurge((Handle)pict);
- dstRect = (**pict).picFrame;
- OffsetRect(&dstRect, -dstRect.left + gDrawRect.left,
- -dstRect.top + gDrawRect.top + 4*lineHeight);
- DrawPicture(pict, &dstRect);
- HPurge((Handle)pict);
-
- }
-
- /* Draw the footer. */
-
- vCoord = gDrawRect.bottom - 2*lineHeight + (**gPrintTE).fontAscent;
- refNum = CurResFile();
- UseResFile(gMyRefNum);
- GetCString(kStrPrintedFor, fmt);
- UseResFile(refNum);
- sprintf((char*)str, fmt, gPrefs.emailAddress, gPrefs.fullName);
- c2pstr((char*)str);
- TruncString(gDrawRect.right - gDrawRect.left - 2*gHalfInch,
- str, smTruncEnd);
- MoveTo(gDrawRect.left + quarterInch, vCoord);
- DrawString(str);
- SetRect(&r, gDrawRect.left, gDrawRect.bottom - 2*lineHeight - 4,
- gDrawRect.right - 2, gDrawRect.bottom - lineHeight + 5);
- PenPat(&qd.gray);
- PenSize(2, 2);
- FrameRect(&r);
- PenPat(&qd.black);
- PenSize(1, 1);
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- IdleProc
-
- The printing idle proc.
- ----------------------------------------------------------------------------*/
-
- static pascal void IdleProc (void)
- {
- OSErr err = noErr;
- short refNum;
-
- refNum = CurResFile();
- UseResFile(gMyRefNum);
- err = GiveTime(true);
- UseResFile(refNum);
- if (err != noErr) PrSetError(iPrAbort);
- }
-
-
-
- /*----------------------------------------------------------------------------
- PrintTheDoc
-
- Print the document.
-
- Entry: title = title for page headers, and print job name
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr PrintTheDoc (char *title)
- {
- short theFirst, theLast;
- short nCopies;
- short prDevice;
- Boolean draftMode;
- TPrStatus prStatus;
- GrafPtr port;
- OSErr err = noErr;
- short i, p;
- TPPrPort prPort;
- Boolean prIsOpen = false;
- Boolean docIsOpen = false;
- Boolean pageIsOpen = false;
-
- MyICReadSharedPrefs(kICRealName);
- MyICReadSharedPrefs(kICEmail);
-
- GetPort(&port);
- PrOpen();
- err = PrError();
- if (err != noErr) goto exit;
- prIsOpen = true;
-
- err = ShowDummyWindow();
- if (err != noErr) goto exit;
- c2pstr(title);
- SetWTitle(FrontWindow(), (StringPtr)title);
- p2cstr((StringPtr)title);
-
- PrValidate(gMyHPrint);
- err = PrError();
- if (err != noErr) goto exit;
- err = Prep();
- if (err != noErr) goto exit;
- theFirst = (**gMyHPrint).prJob.iFstPage;
- theLast = (**gMyHPrint).prJob.iLstPage;
- (**gMyHPrint).prJob.iFstPage = 1;
- (**gMyHPrint).prJob.iLstPage = 9999;
- prDevice = ((**gMyHPrint).prStl.wDev >> 8);
- draftMode = (((**gMyHPrint).prJob.bJDocLoop) & 1) == 0;
- if ((draftMode) && (prDevice == 1))
- nCopies = (**gMyHPrint).prJob.iCopies;
- else
- nCopies = 1;
- prPort = PrOpenDoc(gMyHPrint, nil, nil);
- err = PrError();
- if (err != noErr) goto exit;
- docIsOpen = true;
-
- HideDummyWindow();
-
- SetPort(&prPort->gPort);
- for (i=1; i <= nCopies; i++) {
- for (p = theFirst; p <= theLast; p++) {
- PrOpenPage(prPort, nil);
- err = PrError();
- if (err != noErr) goto exit;
- pageIsOpen = true;
- err = PrintOnePage(p, title);
- if (err != noErr) goto exit;
- PrClosePage(prPort);
- err = PrError();
- if (err != noErr) goto exit;
- pageIsOpen = false;
- }
- }
- PrCloseDoc(prPort);
- err = PrError();
- if (err != noErr) goto exit;
- docIsOpen = false;
-
- if (!draftMode) {
- PrPicFile(gMyHPrint, nil, nil, nil, &prStatus);
- err = PrError();
- if (err != noErr) goto exit;
- }
-
- PrClose();
- err = PrError();
- if (err != noErr) goto exit;
- prIsOpen = false;
-
- (**gMyHPrint).prJob.iFstPage = theFirst;
- (**gMyHPrint).prJob.iLstPage = theLast;
-
- SetPort(port);
- return noErr;
-
- exit:
-
- HideDummyWindow();
- SetPort(port);
- if (pageIsOpen) PrClosePage(prPort);
- if (docIsOpen) PrCloseDoc(prPort);
- if (prIsOpen) PrClose();
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- InitPrint
-
- Intialize printing.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr InitPrint (void)
- {
- OSErr err = noErr;
-
- if (gMyHPrint != nil) return noErr;
- PrOpen();
- err = PrError();
- if (err != noErr) return err;
- err = MyNewHandle(sizeof(TPrint), &gMyHPrint);
- if (err != noErr) goto exit;
- PrintDefault(gMyHPrint);
- err = PrError();
- if (err != noErr) goto exit;
- PrClose();
- return PrError();
-
- exit:
-
- PrClose();
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- PrintError
-
- Handle a printing error.
-
- Entry: err = error code.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- static OSErr PrintError (OSErr err)
- {
- if (err == fnfErr) {
- ErrorMessageNumber(kStrPrintNoDriver);
- return userCanceledErr;
- } else if (err == resNotFound) {
- ErrorMessageNumber(kStrNoPrinterSelected);
- return userCanceledErr;
- } else {
- return err;
- }
- }
-
-
-
- /*----------------------------------------------------------------------------
- DoPageSetup
-
- Handle the "Page Setup" command.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr DoPageSetup (void)
- {
- OSErr err = noErr;
- Boolean prIsOpen = false;
-
- err = InitPrint();
- if (err != noErr) goto exit;
- InitCursor();
- PrOpen();
- err = PrError();
- if (err != noErr) goto exit;
- prIsOpen = true;
- PrValidate(gMyHPrint);
- err = PrError();
- if (err != noErr) goto exit;
- PrepUserInteraction();
- PrStlDialog(gMyHPrint);
- err = PrError();
- if (err != noErr) goto exit;
- PrClose();
- err = PrError();
- if (err != noErr) goto exit;
- return noErr;
-
- exit:
-
- if (prIsOpen) PrClose();
- return PrintError(err);
- }
-
-
-
- /*----------------------------------------------------------------------------
- StartPrint
-
- Present the print job dialog.
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr StartPrint (void)
- {
- Boolean result;
- GrafPtr port;
- OSErr err = noErr;
- Boolean prIsOpen = false;
- short i;
-
- GetPort(&port);
- gMyRefNum = CurResFile();
- err = InitPrint();
- if (err != noErr) goto exit;
- PrOpen();
- err = PrError();
- if (err != noErr) goto exit;
- prIsOpen = true;
- PrValidate(gMyHPrint);
- err = PrError();
- if (err != noErr) goto exit;
- InitCursor();
- err = PrepUserInteraction();
- if (err == noErr) {
- result = PrJobDialog(gMyHPrint);
- err = PrError();
- if (err != noErr) goto exit;
- if (!result) {
- err = userCanceledErr;
- goto exit;
- }
- } else if (err == errAENoUserInteraction) {
- PrintDefault(gMyHPrint);
- err = noErr;
- } else {
- goto exit;
- }
- (**gMyHPrint).prJob.pIdleProc = gIdleProcUPP;
-
- PrClose();
- err = PrError();
- if (err != noErr) goto exit;
- prIsOpen = false;
-
- for (i = 0; i < 10; i++) {
- err = GiveTime(true);
- if (err != noErr) goto exit;
- }
-
- SetPort(port);
- return noErr;
-
- exit:
-
- SetPort(port);
- if (prIsOpen) PrClose();
- return PrintError(err);
- }
-
-
-
- /*----------------------------------------------------------------------------
- PrintText
-
- Print text.
-
- Entry: text = handle to text to be printed.
- start = offset in text of beginning of text to be printed.
- end = offset in text of end of text to be printed.
- title = title for page headers, and print job name
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr PrintText (Handle text, long start, long end, char *title)
- {
- Handle oldText;
- OSErr err = noErr;
- long len;
- Boolean disposeText = false;
- short iFstPage, iLstPage;
- TextStyle style;
-
- gPrintText = true;
-
- MyICReadSharedPrefs(kICPrinterFont);
-
- gText = nil;
- gPrintTE = nil;
- gFirstLines = nil;
- gSectionBreaks = nil;
-
- if (!MemoryAvailable(50000L)) return memFullErr;
-
- err = InitPrint();
- if (err != noErr) return err;
-
- InitCursor();
-
- gDrawRect = (**gMyHPrint).prInfo.rPage;
- gHalfInch = (**gMyHPrint).prInfo.iHRes >> 1;
- gDrawRect.left += gHalfInch;
- gDrawRect.right -= gHalfInch;
-
- GetFontNumber(gPrefs.printingFont, &gFontNum);
- gFontSize = gPrefs.printingSize;
- GetPortTextStyle(&style);
- TextFont(gFontNum);
- TextSize(gFontSize);
- gPrintTE = TENew(&gDrawRect, &gDrawRect);
- SetPortTextStyle(&style);
-
- len = MyGetHandleSize(text);
- if (start > 0 || end < len) {
- len = end - start;
- err = MyNewHandle(len, &gText);
- if (err != noErr) goto exit;
- disposeText = true;
- BlockMoveData(*text + start, *gText, len);
- } else {
- gText = text;
- }
-
- if (len > 0x7fff) {
- gSegmented = true;
- err = MakeSections(gText, &gSectionBreaks, &gNumSections);
- if (err != noErr) goto exit;
- gCurSection = -1;
- err = MyNewHandle(sizeof(long) * (gNumSections+1), &gFirstLines);
- if (err != noErr) goto exit;
- } else {
- gSegmented = false;
- oldText = (**gPrintTE).hText;
- (**gPrintTE).hText = gText;
- TECalText(gPrintTE);
- }
-
- iFstPage = (**gMyHPrint).prJob.iFstPage;
- iLstPage = (**gMyHPrint).prJob.iLstPage;
- err = PrintTheDoc(title);
- (**gMyHPrint).prJob.iFstPage = iFstPage;
- (**gMyHPrint).prJob.iLstPage = iLstPage;
-
- exit:
-
- if (disposeText) MyDisposeHandle(gText);
- MyDisposeHandle(gFirstLines);
- MyDisposeHandle(gSectionBreaks);
- if (gPrintTE != nil) {
- if (!gSegmented) (**gPrintTE).hText = oldText;
- TEDispose(gPrintTE);
- }
-
- return err;
- }
-
-
-
- /*----------------------------------------------------------------------------
- PrintPict
-
- Print a help topic pict.
-
- Entry: pictResID = pict resource id.
- title = title for page headers, and print job name
-
- Exit: function result = error code.
- ----------------------------------------------------------------------------*/
-
- OSErr PrintPict (short pictResID, char *title)
- {
- OSErr err = noErr;
- short iFstPage, iLstPage;
- TextStyle style;
-
- gPrintText = false;
- gPictResID = pictResID;
-
- MyICReadSharedPrefs(kICPrinterFont);
-
- if (!MemoryAvailable(50000L)) return memFullErr;
-
- err = InitPrint();
- if (err != noErr) return err;
-
- InitCursor();
-
- gDrawRect = (**gMyHPrint).prInfo.rPage;
- gHalfInch = (**gMyHPrint).prInfo.iHRes >> 1;
- gDrawRect.left += gHalfInch;
- gDrawRect.right -= gHalfInch;
-
- GetFontNumber(gPrefs.printingFont, &gFontNum);
- gFontSize = gPrefs.printingSize;
- GetPortTextStyle(&style);
- TextFont(gFontNum);
- TextSize(gFontSize);
- gPrintTE = TENew(&gDrawRect, &gDrawRect);
- SetPortTextStyle(&style);
-
- iFstPage = (**gMyHPrint).prJob.iFstPage;
- iLstPage = (**gMyHPrint).prJob.iLstPage;
- err = PrintTheDoc(title);
- (**gMyHPrint).prJob.iFstPage = iFstPage;
- (**gMyHPrint).prJob.iLstPage = iLstPage;
-
- return noErr;
- }
-
-
-
- /*----------------------------------------------------------------------------
- print_InitUPP
-
- Initialize UPPs.
- ----------------------------------------------------------------------------*/
-
- void print_InitUPP (void)
- {
- gIdleProcUPP = NewPrIdleProc(IdleProc);
- }
-